﻿using System;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using Microsoft.SqlServer.Management.Smo;

namespace SimpleCodeGen
{
    /// <summary>
    /// Form1
    /// </summary>
    public partial class Form1 : Form
    {
        #region private members

        /// <summary>
        /// database
        /// </summary>
        private Database _database = null;

        #endregion private members

        private Server _server = null;

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="Form1"/> class.
        /// </summary>
        public Form1()
        {
            // Initialize
            InitializeComponent();

            // Load default settings
            LoadDefaultSettings();

            // messages empty
            lblDbMessage.Text = string.Empty;
        }

        #endregion Constructor

        /// <summary>
        /// Handles the Click event of the btnRefresh control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnRefresh_Click(object sender, EventArgs e)
        {
            DisplayMessage(ConstantHelper.MessageLoadSevers, MessageType.Success);
            Cursor.Current = Cursors.WaitCursor;
            LoadDatabaseServers();
            Cursor.Current = Cursors.Default;
            DisplayMessage("", MessageType.NotSet);
        }

        /// <summary>
        /// Handles the SelectedIndexChanged event of the ddlServers control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void ddlServers_SelectedIndexChanged(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;
            var serverName = ddlServers.Text;
            if (ddlServers.SelectedIndex > -1 && !string.IsNullOrEmpty(serverName))
            {
                ddlDabase.Text = string.Empty;
                var databases = DatabaseHelper.GetDatabases(serverName);
                if (databases != null)
                {
                    ddlDabase.DataSource = databases;
                }
                if (databases.Count() > 0)
                {
                    ddlDabase.SelectedIndex = 0;
                }
            }
            Cursor.Current = Cursors.Default;
        }

        /// <summary>
        /// Handles the Click event of the btnGenerateCode control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnGenerateCode_Click(object sender, EventArgs e)
        {
            // validate
            if (ValidateSettings())
            {
                // save settings
                SaveSettings();

                var parameters = UnBindControls();

                // Get columns from selected table
                var columns = DatabaseHelper.GetColumns(parameters);

                // Generate business object
                ClassGeneratorHelper.GenerateBusinessObjectClass(columns, parameters);

                // Generate Data Provider Interface object
                ClassGeneratorHelper.GenerateDataProviderInterfaceClass(columns, parameters);

                //BusinessObjectGen.GenerateBusinessObject(columns);
                lblDbMessage.Text = "Success: Class Generated Successfully.";
                lblDbMessage.ForeColor = Color.Green;
            }
        }

        /// <summary>
        /// Handles the Click event of the btnTestConnection control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnTestConnection_Click(object sender, EventArgs e)
        {
            // connect to database
            if (ConnectToDatabase())
            {
                // load tables
                LoadTables();

                // load views
                LoadViews();
            }
        }

        /// <summary>
        /// Handles the Click event of the btnOutputFolderOpen control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnOutputFolderOpen_Click(object sender, EventArgs e)
        {
            var dlgHandle = fbdOutputDirectory.ShowDialog();
            if (dlgHandle == DialogResult.OK)
            {
                txtOuputFolderPath.Text = fbdOutputDirectory.SelectedPath;
            }
        }

        /// <summary>
        /// Handles the Click event of the btnClose control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        /// <summary>
        /// Handles the Click event of the btnLoadDefaultSettings control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnLoadDefaultSettings_Click(object sender, EventArgs e)
        {
            LoadDefaultSettings();
        }

        /// <summary>
        /// Handles the Click event of the btnSaveSettings control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnSaveSettings_Click(object sender, EventArgs e)
        {
            SaveSettings();
        }

        #region Helper Methods

        /// <summary>
        /// Loads the database servers.
        /// </summary>
        private void LoadDatabaseServers()
        {
            ddlServers.Text = "";
            ddlServers.DataSource = DatabaseHelper.GetDatabaseServers();
            ddlServers.SelectedIndex = 0;
        }

        /// <summary>
        /// Connects to database.
        /// </summary>
        /// <returns></returns>
        private bool ConnectToDatabase()
        {
            var result = false;
            var parameters = UnBindControls();
            var message = string.Empty;

            _database = DatabaseHelper.Connect(parameters, ref message);
            if (_database != null && string.IsNullOrEmpty(message))
            {
                DisplayMessage(ConstantHelper.MessageSuccessConnectedToDatabase, MessageType.Success);
                result = true;
            }
            else
            {
                DisplayMessage(message, MessageType.Error);
            }
            return result;
        }

        /// <summary>
        /// Loads the tables.
        /// </summary>
        private void LoadTables()
        {
            // get list of tables
            ddlTables.Items.Clear();
            ddlTables.Items.Add(new ComboboxItem() { Text = ConstantHelper.PleaseSelect, Value = "" });

            if (_database != null && _database.Tables.Count > 0)
            {
                for (int i = 0; i < _database.Tables.Count; i++)
                {
                    var item = new ComboboxItem();
                    item.Text = string.Format("{0}.{1}", _database.Tables[i].Schema, _database.Tables[i].Name);
                    item.Value = _database.Tables[i].Name;
                    ddlTables.Items.Add(item);
                }
            }

            // select
            ddlTables.SelectedIndex = 0;
        }

        /// <summary>
        /// Loads the views.
        /// </summary>
        private void LoadViews()
        {
            // get list of views
            ddlViews.Items.Clear();
            ddlViews.Items.Add(new ComboboxItem() { Text = ConstantHelper.PleaseSelect, Value = "" });

            if (_database != null && _database.Views.Count > 0)
            {
                for (int i = 0; i < _database.Views.Count; i++)
                {
                    var item = new ComboboxItem();
                    item.Text = string.Format("{0}.{1}", _database.Views[i].Schema, _database.Views[i].Name);
                    item.Value = _database.Views[i].Name;
                    ddlViews.Items.Add(item);
                }
            }

            // select
            ddlViews.SelectedIndex = 0;
        }

        /// <summary>
        /// Binds the controls.
        /// </summary>
        /// <param name="customParameter">The custom parameter.</param>
        private void BindControls(CustomParameter customParameter)
        {
            if (customParameter != null)
            {
                ddlServers.Text = customParameter.DatabaseServerName;
                ddlDabase.Text = customParameter.DatabaseName;
                rblSql.Checked = customParameter.DatabaseSQLAuthenticationMode;
                rblWindows.Checked = !rblSql.Checked;
                if (rblSql.Checked)
                {
                    txtUserName.Text = customParameter.DatabaseUserName;
                    txtPassword.Text = customParameter.DatabasePassword;
                }
                else
                {
                    txtUserName.Text = string.Empty;
                    txtPassword.Text = string.Empty;
                }

                txtCompanyName.Text = customParameter.CompanyName;
                txtCopyright.Text = customParameter.Copyright;
                txtDeveloperName.Text = customParameter.DeveloperName;
                txtClassName.Text = customParameter.ClassName;
                txtOuputFolderPath.Text = customParameter.OutputFolderPath;

                chkAll.Checked = customParameter.GenerateClassAll;
                chkBusinessObject.Checked = customParameter.GenerateClassBusinessObject;
                chkBusinessManager.Checked = customParameter.GenerateClassBusinessManager;
                chkBusinessManagerInterface.Checked = customParameter.GenerateClassBusinessManagerInterface;
                chkDataProvider.Checked = customParameter.GenerateClassDataProvider;
                chkDataProviderInterface.Checked = customParameter.GenerateClassDataProviderInterface;
                chkMvcModel.Checked = customParameter.GenerateClassMvcModel;
            }
        }

        /// <summary>
        /// Uns the bind controls.
        /// </summary>
        /// <returns></returns>
        private CustomParameter UnBindControls()
        {
            var customParameter = new CustomParameter();

            customParameter.DatabaseServerName = ddlServers.Text;
            customParameter.DatabaseSQLAuthenticationMode = rblSql.Checked;
            if (rblSql.Checked)
            {
                customParameter.DatabaseUserName = txtUserName.Text;
                customParameter.DatabasePassword = txtPassword.Text;
            }
            else
            {
                customParameter.DatabaseUserName = string.Empty;
                customParameter.DatabasePassword = string.Empty;
            }

            customParameter.DatabaseName = ddlDabase.Text;
            customParameter.CompanyName = txtCompanyName.Text;
            customParameter.Copyright = txtCopyright.Text;
            customParameter.DeveloperName = txtDeveloperName.Text;
            customParameter.ClassName = GetClassName();
            customParameter.OutputFolderPath = txtOuputFolderPath.Text;
            customParameter.TableName = GetSelectedTableName();
            customParameter.SchemaName = GetSelectedSchemaName();

            customParameter.GenerateClassAll = chkAll.Checked;
            customParameter.GenerateClassBusinessObject = chkBusinessObject.Checked;
            customParameter.GenerateClassBusinessManager = chkBusinessManager.Checked;
            customParameter.GenerateClassBusinessManagerInterface = chkBusinessManagerInterface.Checked;
            customParameter.GenerateClassDataProvider = chkDataProvider.Checked;
            customParameter.GenerateClassDataProviderInterface = chkDataProviderInterface.Checked;
            customParameter.GenerateClassMvcModel = chkMvcModel.Checked;

            return customParameter;
        }

        /// <summary>
        /// Displays the message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="messageType">Type of the message.</param>
        private void DisplayMessage(string message, MessageType messageType)
        {
            switch (messageType)
            {
                case MessageType.Error:
                    lblDbMessage.ForeColor = Color.Red;
                    break;
                case MessageType.Success:
                    lblDbMessage.ForeColor = Color.Green;
                    break;
                case MessageType.Warning:
                    lblDbMessage.ForeColor = Color.Orange;
                    break;
                case MessageType.Progress:
                    lblDbMessage.ForeColor = Color.Blue;
                    break;
            }
            lblDbMessage.Text = message;
        }

        /// <summary>
        /// Loads the default settings.
        /// </summary>
        private void LoadDefaultSettings()
        {
            try
            {
                // Bind controls
                BindControls(UtilityHelper.GetSettings());

                // display message
                DisplayMessage(ConstantHelper.MessageSuccessLoadSettings, MessageType.Success);
            }
            catch (Exception exception)
            {
                // display message
                DisplayMessage(exception.Message, MessageType.Error);
            }
        }

        /// <summary>
        /// Saves the settings.
        /// </summary>
        private void SaveSettings()
        {
            try
            {
                // UnBind controls
                UtilityHelper.SaveSettings(UnBindControls());

                // display message
                DisplayMessage(ConstantHelper.MessageSuccessSaveSettings, MessageType.Success);
            }
            catch (Exception exception)
            {
                // display message
                DisplayMessage(exception.Message, MessageType.Error);
            }
        }

        /// <summary>
        /// Gets the name of the selected table.
        /// </summary>
        /// <returns></returns>
        private string GetSelectedTableName()
        {
            var result = string.Empty;
            var item = rblTable.Checked ? (ComboboxItem)ddlTables.SelectedItem : (ComboboxItem)ddlViews.SelectedItem;
            if (item != null && !string.IsNullOrEmpty(item.Value.ToString()))
            {
                result = item.Value.ToString();
            }
            return result;
        }

        /// <summary>
        /// Gets the name of the selected schema table.
        /// </summary>
        /// <returns></returns>
        private string GetSelectedSchemaName()
        {
            var result = string.Empty;
            var item = rblTable.Checked ? (ComboboxItem)ddlTables.SelectedItem : (ComboboxItem)ddlViews.SelectedItem;
            if (item != null && !string.IsNullOrEmpty(item.Value.ToString()))
            {
                var name = item.Text;
                var index = name.LastIndexOf(".");
                if (index > -1)
                {
                    result = name.Substring(0, index);
                }
            }
            return result;
        }

        /// <summary>
        /// Gets the name of the class.
        /// </summary>
        /// <returns></returns>
        private string GetClassName()
        {
            var result = txtClassName.Text.Trim();

            if (string.IsNullOrEmpty(result))
            {
                var item = (ComboboxItem)ddlTables.SelectedItem;
                if (item != null && !string.IsNullOrEmpty(item.Value.ToString()))
                {
                    result = item.Value.ToString();
                }
            }

            return result;
        }

        /// <summary>
        /// Validates the settings.
        /// </summary>
        /// <returns></returns>
        private bool ValidateSettings()
        {
            var result = false;
            var parameters = UnBindControls();
            if (parameters != null)
            {
                if (string.IsNullOrEmpty(parameters.TableName))
                {
                    DisplayMessage(ConstantHelper.MessageErrorTableSelection, MessageType.Error);
                }
                else if (!System.IO.Directory.Exists(parameters.OutputFolderPath))
                {
                    DisplayMessage(ConstantHelper.MessageErrorOutputFolderNotExits, MessageType.Error);
                }
                else
                {
                    result = true;
                }
            }

            return result;
        }

        #endregion Helper Methods
    }
}